/**
 * 210824：升级修改【three.js r120-r131】
 */
let THREE=require('three');
import Collider from './collider';
import CONST from '../collision-const';

/**
 * 球体
 * @param values {color,radius} color:THREE.Color,radius:半径
 */
export default class SphereCollider extends Collider{
    constructor(values={}){
        super(values);
    }

    //-------------------------------------------对外属性及方法----------------------------------------

    /**
     * 获取类型
     * @returns {string}
     */
    get colliderType(){
        return CONST.COLLIDER_TYPE_SPHERE;
    }

    /**
     * 获取包围盒（世界空间）
     * @returns {this}
     */
    get bounds(){
        return this._box.clone().applyMatrix4(this.matrixWorld);
    }

    /**
     * 获取包围盒（局部空间）
     * @returns {box}
     */
    get box(){
        return this._box.clone();
    }

    /**
     * 获取包围球（局部空间）
     * @returns {Sphere}
     */
    get sphere(){
        return this._shape.clone();
    }

    /**
     * 获取半径
     * @returns {*}
     */
    get radius(){
        return this._props.radius;
    }

    /**
     * 设置半径
     * @param radius
     */
    set radius(radius){
        if(radius===this._props.radius)return;
        this._props.radius=radius;
        this._shape.getBoundingBox(this._box);
        if(this._debug)this._debug.scale.set(radius,radius,radius);
    }

    /**
     * 获取颜色
     * @returns {*}
     */
    get color(){
        return this._props.color;
    }

    /**
     * 设置颜色
     * @param color
     */
    set color(color){
        let c=this._props.color;
        if(color.r===c.r&&color.g===c.g&&color.b===c.b)return;
        this._props.color.copy(color);
        for(let c of this._debug.children){
            c.material.color=this._props.color;
        }
    }

    /**
     * 销毁
     */
    dispose(){
        super.dispose();
        this._box=null;
        this._invMat=null;
        this._ray=null;
    }

    //---------------------------------------私有属性及方法-------------------------------------

    /**
     * 绘制调试
     * @private
     */
    _createDebug(){
        if(this._debug)return;
        this._debug=new THREE.Object3D();

        //20210824
        // let g=new THREE.Geometry();
        // let u=Math.PI*2/35;
        // for(let i=0;i<36;i++){
        //     let x=Math.sin(u*i);
        //     let y=Math.cos(u*i);
        //     g.vertices.push(new THREE.Vector3(x,y,0));
        // }
        let g=new THREE.BufferGeometry();
        let u=Math.PI*2/35;
        let ps=new Float32Array(36*3);
        for(let i=0;i<36;i++){
            ps[i*3]=Math.sin(u*i);
            ps[i*3+1]=Math.cos(u*i);
            ps[i*3+2]=0;
        }
        g.setAttribute('position',new THREE.BufferAttribute(ps,3));

        let m=new THREE.LineBasicMaterial({color:this._props.color});
        let c=new THREE.Line(g,m);
        this._debug.add(c);
        let c1=c.clone();
        c1.rotation.x=Math.PI*0.5;
        this._debug.add(c1);
        let c2=c.clone();
        c2.rotation.y=Math.PI*0.5;
        this._debug.add(c2);

        let r=this._props.radius;
        this._debug.scale.set(r,r,r);
        this.add(this._debug);
    }

    /**
     * 销毁调试
     * @private
     */
    _destroyDebug(){
        if(!this._debug)return;
        this.remove(this._debug);
        for(let c of this._debug.children){
            c.geometry.dispose();
            c.material.dispose();
        }
        this._debug=null;
    }

    /**
     * 初始化属性
     * @private
     */
    _initProps(){
        super._initProps();
        this._props.radius=this._values.radius||0.5;
    }

    /**
     * 初始化变量
     * @private
     */
    _initVariable(){
        super._initVariable();
        this._box=new THREE.Box3();
        this._invMat=new THREE.Matrix4();
        this._ray=new THREE.Ray();
    }

    /**
     * 初始化形状
     * @private
     */
    _initShape(){
        this._shape=new THREE.Sphere(this._center,this._props.radius);
        this._shape.getBoundingBox(this._box);
    }

    /**
     * 初始化射线检测函数
     * @private
     */
    _initRaycast() {
        this._raycast=(raycaster,intersects,target)=>{
                let object=this;
                let matrixWorld = this.matrixWorld;
                if ( raycaster.ray.intersectsSphere( this.sphere.applyMatrix4(matrixWorld) ) === false ) return;
                // this._invMat.getInverse( matrixWorld );20210824
                this._invMat.copy( matrixWorld ).invert();
                this._ray.copy( raycaster.ray ).applyMatrix4( this._invMat );
                let intersectPoint=new THREE.Vector3();
                if(this._ray.intersectSphere(this._shape,intersectPoint)){
                    intersectPoint.applyMatrix4(matrixWorld);
                    let distance=raycaster.ray.origin.distanceTo(intersectPoint);
                    intersects.push({
                        distance:distance,
                        distanceToRay:0,
                        index: null,
                        face: null,
                        point:intersectPoint,
                        object:target?target:object,
                        shape:object,
                    });
                }
            };
    }
}